 <!-- <!-- <!DOCTYPE html>
档格式：声明HTML5文档
!的意义：严格模式：标签必须闭合
        混搭模式：标签可以不用闭合
<html lang="en">lang设置文档内容的语言  "en" 表示英语（English）"zh-cn" 表示简体中文知等等
     html结构层
         css表现层
         js行为层 
<head>
     头部 
    <meta charset="UTF-8">
    规定文档编码格式 
         UTF_8可以解析中文的
    <meta name='viewport' content='width=device-width;initial-scale=1,maximum-scale=1,minimum-scale=1,userscalable=no'>
    用户网页的可视区域。          宽度为移动端宽度     初始化比例1:1     最大缩放比列1:1   最小缩放比列    是否允许用户手动缩放 
    一般情况下移动端都不会允许缩放
    //userscalable的值为：no/yes  0/1  禁止/允许-->
    <meta name=“description” content=“一个为让人嫉妒的网站”/>
     网站内容描述 
    <meta name='keywords' content='小孩,嫉妒' />
     关键字 rel链接的资源类型
    <link rel="icon" href="images/07.jpg"> 
    设置头部图标
    <link rel="stylesheet" href="">
        引入css文件    响应式
    <title>Document</title>         
    页面眉头，标题 
    <script src='http://libs.baidu.com/jquery/2.0.0/jquery.js'></script>
    <style>
    </style>
</head>
<body>
alt属性
        <img src="" alt="这是个图片" title='这是一张图片'>//当图片加载不出来时，会出现alt属性；  
title属性:      鼠标悬停到这个标签上显示title的属性值所有dom元素都有title属性，
        <a href="" title='这是一个a链接'>链接</a>
iframe标签：    嵌入式链接
        <iframe src="https://www.baidu.com" width='500px' height='500px'>baidu </iframe>
        <div id="btn">js跳转页面</div>
a标签：
        超链接：链接资源或内容定位目标    href='地址'
	锚点/锚链接：定位页面内容的       href='#one'     定位到某个标签添加id名：id='one'
                <a href="#one">top</a>
                <br>
                <p id='one'></p>
        target属性: 
                _blank  跳转到新的页面
                _parent 
                _self  
                _top   


引入文件：
        ../找上一个文件夹      文件名/  找下一个文件夹
    <script>
    // h1标题在页面中只能使用一次
    </script>
</body>
</html> 
表单元素：
        <form action="请求地址" method="get/post">get：安全性弱；post：不暴露，安全性高
                <input type="text"/>     单行文本
                <input type="password"/> 密码框
                <input type="submit"/>   提交按钮
                <input type="number"/>   数字框
                <input type="tel"/>      数字框
                <input type="reset"/>    重置按钮
                <input type="button"/>   按钮
                <input type="file"/>     文件
                <input type="search"/>   搜索框
                <select name="" id="">   下拉列表
                   <option value="">1</option>下拉列表项
                   <option value="">2</option>
                   <option value="">3</option>
                </select>
                <textarea name="" id="" cols="30" rows="10"></textarea>多行文本
        
        单选按钮
                radio单选按钮的一些用法：一组单选按钮中只能选一个；
                name：让同一组的单选按钮，name取值一定要一致，比如以上的所有radio单选按钮的name值都为sex，这样同一组的单选按钮才可以起到单选的作用。
                                <input type="radio" name='sex' checked='checked'/>
                                <input type="radio" name='sex'/>
        checkbox多选按钮
                checkbox复选框；用户从给定的选择中选取一个或若干选项。
                <input type="checkbox"/>复选框
        checked:  当设置 checked="checked" 时，该选项被默认选中  
                注：当元素中有checked属性时，其值无论是什么，都是被选中状态；
                所以需要js或jq来设置checked属性为true或false；切忌带引号，否则会出错。
                input.checked=false;	js
                $('#input').prop('checked',false)  jq
        lable关联 label元素不会向用户呈现任何特殊效果。不过，它为鼠标用户改进了可用性。如果您在 label 元素内点击文本，就会触发此控件
                就是说，当用户选择该标签时，浏览器就会自动将焦点转到和标签相关的表单控件上。
                        <label for="input-id" class="col-sm-2"></label>
                
        </form>

弹性盒子：
                父级：   display:flex;      使得子元素在一行显示，永远不掉块；
                子级：   flex:1;        设置弹性盒子的子元素(盒模型)如何分配空间：占的份数；
                  出现的bug:弹性盒子的所有子元素的高度总是相同
盒模型：
                content->padding->border->margin 


js的组成部分：
                1、 ECMAScript  核心语法
		2、 DOM	        文档对象模型：操作页面用的。
		3、 BOM         浏览对象模型:与浏览器交互的方法。
长度和下标：
                长度是从1开始数的；
                下标是从0开始数的；可以根据长度计算下标：arr.length-1;

注：类数组拥有数组的长度属性，但不具备数组的方法
js获取元素的方法：
                1.通过类名获取元素：返回类数组
                        var li=document.getElementsByClassName('box')
                        console.log(li)   li[0]
                2.通过标签获取元素：返回类数组
                        var li=document.getElementsByTagName('li')
                        console.log(li)  li[0]
                3.通过id获取元素：注：js中通过id使用元素时，可以不用获取元素；
                        var box2=document.getElementById('box2')  获取1个
                        console.log(box2)
                4.通过选择器获取一个元素
                        var li=document.querySelector('.box1')  获取1个
                        console.log(li)
                5.通过选择器获取多个元素；返回类数组
                        var li=document.querySelectorAll('li')
                        console.log(li)  li[0]
                6.获取html的方法：
                        console.log(document.documentElement)
                        兼容ie浏览器的写法
                                console.log(document.body)
                也可以这样获取：
                        document.getElementsByClassName('list')  在当前页面中获取
                        document.getElementsByClassName('list')[0].getElementsByTagName('div') 多个链着获取
                        box.getElementsByTagName('div') 在某个元素中获取
布尔方法：
                其他类型数据转换为Boolean类型数据——Boolean()方法
                                数据类型	转换为true		转换为false
                                Boolean		true		       false
                                String		非空字符串		空字符串
                                Number		非零数值		0和NaN
                                Object		任何对象		null
                                Undefined       n/a(不适用)		undefined
        

                
变量：var           
                一次同时声明多个变量，用','分割
                        var a1,a2,a3;
                        var n1=100,n2=200,n3=300;
                        var n1=100,n2,n3=200;
                        
                规则：必须要遵守的，不遵守就会出错
                        1.变量名只能由数字、字母、下划线、'$'符组成 一个区分大小写 数字不可以开头
                        2.避免关键字&保留字
                        3.变量名不能有空格；
                规范：建议遵守，不遵守不会报错；
                        1.变量名尽量有意义(语义化)
                        2.驼峰命名法；
                                当一个变量由多个单词组成的时候，第二个单词的首字母要大写；
                                var userName='小明',
                        3.不能使用中文命名   有效果的 
                                var 小明='世界';

                作用域：就是变量的使用范围；var 
                        **只有函数可以生成作用域；
                作用域分两种：
                        一个你打开的页面就是一个全局作用域(window)；定义在全局作用域中的变量为全局变量
                        每一个函数都是一个私有作用域；定义在私有作用域中的变量为局部变量；
                作用域对变量的限制：
                         一个变量只能在自己的作用域内部使用；
                         或者在下级作用域里面使用；
                         不能在上级作用域里面使用；
                         **作用域和函数的调用没有关系，在函数中定义的时候就确定了作用域；
                                var num=100;
                                function fn1(){
                                console.log(n1)
                                }
                                function fn2(){
                                var n1=100;
                                fn1()//虽然在这里调用执行函数中的代码；但是作用域访问变量时只跟函数的定义有关系；
                                }
                                fn2()//fn1 is not defined
                        
                变量访问规则：
                        注：找带var的变量；
                                function fn(){
                                  console.log(a)//a is not defined
                                  a=10;
                                }
                                fn()
                        自己有就用自己的；
                        自己没有就去上一级查找；
                        如果还没有就再去上一级查找；
                        直到window上都没有，那么就报错：变量 is not defined;
                        ##在全局作用域中访问变量的时候，要注意看局部作用域中有没有进行对全局变量的赋值；
                                var num=100;
                                function fn(){
                                    var num=200;
                                    function fn(){
                                         var num=300;
                                         console.log(num)//先找自己作用域里的变量，有直接使用，停止查找；
                                    }
                                    fn()//先找自己做用域里的fn函数，有就直接执行fn函数中的代码，停止查找；
                                }
                                fn()//300 访问时，先找全局作用域的中fn函数
                赋值规则：
                        自己有就给自己赋值；
                        自己没有就给上一级赋值；
                        上一级没有就给再上一级的赋值；
                        直到window上也没有，那么就把这个变量定义为全局变量再赋值；
                        注：
                                如果是连串赋值：从右向左赋值；
                                var a=b=c;
                                先变量提升，然后再从右向左赋值；
                                var a;
                                b=c;没有找到变量，会报错b is not defined;
                        // var num=10//自己作用域中没有，上一级也没有，再上一级到了全局作用域，有直接赋值，现在全局作用域中的num被赋值为了300
                        //如果全局作用域中也没有，就会把这个变量定义为全局变量再赋值；
                        function fn(){
                        //   var num=100;//先在自己作用域中找，如果没有就去上一级作用域，有就直接赋值，现在这个作用域中num被赋值成了300；
                          function fn(){
                        //     var num=200;
                            num=300;//是在给num赋值；
                        //先在自己作用域里面找，有直接赋值；现在自己作用域中的num被赋值为了300
                            console.log(num)//300 300 300 300
                          }
                          fn()
                          console.log(num)//100 300 300 300
                        }
                        fn()
                        console.log(num)//10 10 300 300

                变量提升: 当一个执行环境加载时 先将该环境中的var和function关键字定义的变量和函数先定义出来 再从上往下执行代码
                         var和function  函数优先置顶：函数提升要比变量提升的优先级要高一些，且不会被变量声明覆盖，但是会被变量赋值之后覆盖。
                         注：   var 变量提升不受if的限制；
                                return 后面的代码虽然不执行，但是会进行预解析
                                        console.log(fn)//不会被变量声明覆盖
                                        var fn=10;
                                        console.log(fn)//会被变量赋值之后覆盖
                                        function fn(){

                                        }
                        注：变量提升时只是定义函数，并没有执行函数中的代码，当调用函数时才会执行函数中的代码；
                                        

js中中括号与点语法的区别；
                作用：获取某个变量的值；
                [] 获取值：
                        如果是变量  [变量] 如果是属性  ['属性']
                '.'点语法获取值：
                        点语法点的是属性；即： .属性
js中的运算符:        
                = 一个等号相当于赋值；var a=10;
                == 判断两个数据值是否相等；
                ===判断两个数据的值和类型是否相等；
                !=不相等
                +加法；
                -减法
                *乘法
                /除法
                %求余数:除数小于被除数的为除数，能被整除的为0；
                ++ 递增     连串运算时:a++:先带入运算再自增；++a:先自增再带入运算；包括console.log(a++)输出时
                                单独运算时：不管是++a还是a++;都会自增1；
                -- 递减      用法同上；
                +=递增       x+=y x=x+y
                &&逻辑与:
                        逻辑与（& & ）（并且）
                        会将操作数转换为Boolean类型
                        第一个值          第二个值           返回
                        true               true            true
                        true               false           false
                        false              跳过第二个值      false
                        用于if语句的规则：
                                当a和b同时为true时返回的就是true；但凡有一个为false,返回的就是false；第一个表达式如果是错误的会直接不验证第二个表达式
                        用于cosnole/alert/变量的规则：
                                        如果&&前面的表达式返回的是false，那么不管后面返回的是false还是true，都是返回前面表达式的值
                                        如果&&前面的表达式返回的是true，那么不管后面返回的是false还是true，都是返回后面表达式的值；
                                        注：连串计算只有&&时，从左向右依次计算，遇到false，就不计算后面的了
                                        var a=0&&1;
                                        console.log(a)//0 
                                        //0会返回false，返回前面的表达式的值
                                        var a=1&&0;
                                        console.log(a)//0
                                        //1会返回true，返回后面的表达式的值
                ||逻辑或:
                        逻辑或（||）（或者） 
                        会将操作数转换为Boolean类型 
                        第一个值         第二个值               返回 
                        true            跳过第二个值            true 
                        false           true                   true 
                        false           false                  false 
                        用于if语句的规则：
                                当a和b同时为false,返回的就是false；但凡有一个为true,返回的就是true；第一个表达式如果是正确的会直接不验证第二个表达式 
                        用于cosnole/alert/变量的规则：
                                        如果||前面的表达式返回的是false，那么不管后面返回的是false还是true，都是返回后面表达式的值
                                        如果||前面的表达式返回的是true，那么不管后面返回的是false或true，都是返回前面表达式的值
                                        注：连串运算只有||时，从左向右计算，如果遇到true，就不执行后面的了
                                        console.log(0||1)//1
                                        //0会返回false,会返回后面一个表达式的值
                                        console.log(1||0)//1
                                        //1会返回true，会返回前面表达式的值
                                alert( (1 && 3 || 0) && 4 ); //结果4 ①
                                //先比较1&&3会返回3||0会返回3&&4会返回4
                                alert( 1 && 3 || 0 && 4 ); //结果3 ②
                                //先比较1&&3会返回3  0&&4返回0  3||0会返回3
                                alert( 0 && 3 || 1 && 4 ); //结果4 ③
                                //先比较0&&3会返回0 1&&4会返回4  0||4返回4
                !逻辑非
                        !false就相当于true
                运算规则:
                        字符串的加法运算：任何类型和字符串做加法运算都是字符串的拼接
                        字符串的减法运算：纯数字字符串才能转为数值，其他的都是NaN;
                        除了字符串的运算：都会将其他类型转换为数值
                        非零非空即为真  注：有空格不属于空，[]和{}不属于空；

        案例：
                如果一个属性只有两个值，可以用！
                        isPlay=!isPlay
        基本数据类型的拷贝问题：不会互相影响；相当于复制内容
                        var a=10;
                        var b=a;
                        b=20;
                        console.log(a)//10
                        console.log(b)//20
es6中的变量: 
                es5中:var 叫做定义变量
                es6中：
                let 叫做定义变量
                const叫做定义常量：定义之后，不能修改；
		(let、const)与var的区别：
                        var:可以重复声明；会域解析；根据函数划分作用域；var定义的全局变量会成为winodw的属性 
                        let与const：不能重复声明；不会域解析；根据代码块划分作用域'{}'；
                let与const的区别：
                        let：可以在声明的时候不赋值；可以重新赋值
                        const:在声明的时候必须赋值；一经赋值不能更改：注：如果是对象可以改对象中的属性或方法；不能修改对象的地址
		// 1.  
			var 可以重复声明
				// var num=100;
				// var num=200;
				// console.log(num)
			let和const 不能重复声明
				// let n=20;
				// let n=30;
				// console.log(n)
                                计算题：
                                        {
                                        let a=20;//let声明的变量不能重复定义
                                        var a='10';
                                        console.log(a)//报错  
                                        
                                        var b='10';
                                        let b=20;
                                        console.log(b)
                                        }
		// 2.  
			var 会进行预解析(可以在赋值之前使用，只不过拿到的是undefined)
					// console.log(num)//undefined
					// var num=100;
					// console.log(num)//100
			let和const 不会预解析(就是在声明之前不能使用)
					// console.log(num)//报错ReferenceError
					// let num=100;
					// console.log(num)
		// 3.
			var只被函数限定作用域：
					// (1)
					// function fn(){
					// 	var num=100
					// }
					// fn()
					// console.log(num)//num is not defined
					// (2)
					// if(true){
					// 	var num=200;
					// }
					// console.log(num)//200
			let和const 会生成块级作用域,就是会被任何一个可以书写代码的{} 限制使用范围
					// if(true){
					// 	let num=200;//在块级作用域内定义的变量，只能在这个作用域内输出或使用；
					// }
					// console.log(num)//num is not defined
                let与const的区别：
			//1.
				let 可以在声明的时候不进行赋值
							// let num;
							// console.log(num)//undefined
				const在声明的时候必须赋值
							// const num;
							// console.log(num)//报错
			// 2.
				let 可以重新赋值；
						// let num=100;
						// num=200;
						// console.log(num)//200
				const  声明的常量一经赋值不能更改；
						// const num=100;
						// num=200;
						// console.log(num)//报错
					注：如果是一个对象，只要不更改地址，就不会报错，即可以更改对象中的属性或方法；
						// const obj={
						// 	name:'小明',
						// 	age:10
						// }
						// obj.name='小红'
						// console.log(obj)
                                                // obj={
                                                //    name:'李丽丽'
                                                // }
                                                // console.log(obj)//报错
				一个js文件中，通常是常量多还是变量多:常量多(获取元素，定义函数)
				声明变量的时候(首选就是let或const)
				如果定义基本数据类型(一般用let)
				如果定义复杂数据类型(一般都用const)
				
		案例注意问题
			// (1) i为全局变量；
			// for(var i=0;i<inputs.length;i++){//注inputs的长度为5
			// 	inputs[i].onclick=function(){
			// 		console.log(i)//5
			// 	}
			// }
			//浏览器解析过程：
				// {//就是for循环的花括号
				// 	var i=0;//花括号不显示变量i,所以i为全局变量
				// 	inputs[0].onclick=function(){console.log(i)//此时不会输出，点击时才会输出}
				// }
				// ....
				// {
				// 	var i=4;
				// 	inputs[4].onclick=function(){console.log(i)}
				// }
				// {
				// 	var i=5;
				// 	循环结束
				// }
				//当我点击[0]的时候解析i变量，先在函数自己的作用域里面查找有没有i变量，如果有就优先使用
				//自己作用域里的变量，如果没有就去上一级查找，上一级就是全局作用域 i==5;打印出来就是5
			// (2)
					// for(let i=0;i<inputs.length;i++){//注inputs的长度为5
					// 	inputs[i].onclick=function(){
					// 		console.log(i)//5
					// 	}
					// }
					//浏览器解析过程：
						// {
							// let i=0;
							// inputs[0].onclick=function(){console.log(i)}//此时还不会输出i，点击时才会输出i
						// }
						// ...
						// {
							// let i=4;
							// inputs[4].onclick=function(){console.log(i)}
						// }
						// {
							// let i=5;
							//循环结束
						// }
							//当点击第0的时候，先在自己作用域里面查找变量，如果有优先使用自己作用域变量里面的，
							//如果没有，就去上一级作用域里查找，上一级作用域就是for循环中的花括号，这个
							// 作用域里面有一个i==0;打印出来就是0；
es6解构赋值：
	作用：快速从对象或数组中拿出对应的数据；
		1.解构对象：
			使用{}结构对象；
			语法：const {变量(属性)}=对象名
			要求：这个变量必须是对象中的某一个（属性）成员(不然拿到的是undefined)；
			在解构的时候可以赋值一个别的名字；
			解构时，可以嵌套对象使用；

                                var obj={
                                name:'小明',
                                age:20,
                                sex:'男'
                                }
                                const {name,age,sex,height}=obj
                                const {name}=obj等价于=> const name=obj.name
                                console.log(name)//可以直接使用
                                console.log(height)
			(1)在解构的时候可以赋值一个别的名字；
			语法：{对象中的某一个成员名称：别名}=对象
                                const {name:a,age,sex:b}=obj等价于=>const a=obj.name   冒号后面的a等于对象.冒号前面的name
                                console.log(a)
                                console.log(b)
			(2)解构时，可以嵌套对象使用；
				var obj={
				name:'我是obj对象',
				data:{
                                        name:'我是obj.data对象',
                                        age:18,
                                        list:{
                                                name:'我是obj.data.list对象',
                                                age:20
                                                }
				        }
				}
				const {data:{age:a,list:{age:b}}}=obj
				console.log(a,b)
				等价于：const {age:a,list:{age:b}}=obj.data
				const a=obj.age
				const {age:b}=obj.data.list
				const b=obj.data.list.age
-----------------------------------------------------------------------------------------------
		2.解构数组：
			使用 [] 解构数组；
			语法：const [变量]=数组;
			可以嵌套使用；
                                const arr=['hello','world']
                                const [a,b]=arr
                                console.log(b)
                                console.log(a)
                                (1)可以嵌套使用;
                                const arr=['hello','world',[1,2]]
                                const [a,b,[ab,ba]]=arr;
                                console.log(ab,ba)
                
展开运算符: ...
		作用：
		1.进行数组拼接；
                        (1) const arr1=[1,2,3]
                        const arr2=[4,5,6]
                        const arr3=[7,8,9,...arr1,...arr2]
                        console.log(arr3)
                        console.log(...arr1)
                        (2)
                        var res=Math.max(...arr1)//注：max括号中只能写序列的形式，可以用展开运算符展开；
                        console.log(res)
		2.进行函数的参数传递；
		展开对象
                        (1).一般是合并对象使用；
                                var obj1={
                                name:'小明',
                                sex:'男'
                                }
                                var obj2={
                                ...obj1,
                                age:20
                                }
合并运算符：     合并成数组
		...写在形参时，是合并；合并成数组中返回
		    箭头函数没有arguments,可以使用...创造一个；使用时需要加小括号；
                        (1)function fn(...arg){
                        console.log(arg)//数组 [1,2,3,4,5,6]
                        console.log(arguments)//类数组
                        }
                        fn(1,2,3,4,5,6)

                        (2) function fn(a,b,...arg){//把剩余的合并
                        console.log(arg)//[3,4,5,6]
                        }
                        fn(1,2,3,4,5,6)

                        (3)var fn=(...arg)=>{console.log(arg)//形参，需要加括号；
                        fn(1,2,3,4,5,6,7)//[1,2,3,4,5,6,7]

		...写在解构数组时，是合并；
                        const arr=[1,2,3,4,5];
                        const [a,...b]=arr//把剩余的合并
                        console.log(a)
                        console.log(b)
字符串：
        方法：
                 var str=new String('nishishei')  构造函数
                 var str1='nishishei'  声明一个字符串
                字符串有下标，也有长度；
                字符串.length:返回字符串的长度； 注：''.length//0 空字符串的长度为0；
                字符串有下标：str[0];允许通过下标访问字符
                字符串.indexOf('要查找的字符串')：从左到右查找，返回字符串首次出现的下标；如果没找到返回-1；
                字符串.lastIndexOf('要查找的字符串')：从右到左找，返回字符串首次出现的下标，如果没找到返回-1；注：下标顺序不会变
                字符串.charAt(下标)通过下标找字符； 找不到就返回空
                字符串.slice(起始下标，结束下标)：截取字符串，注：但不包含结束下标；如果只有一个参数，就从起始下标截取到最后；
                字符串.substring(起始下标，结束下标)：截取字符串；注：但不包含结束下标；如果只有一个参数，就从起始下标截取到最后；
                字符串.substr(起始下标，结束下标)：截取字符串；注：但不包含结束下标；如果只有一个参数，就从起始下标截取到最后；
                字符串.replace(原,新) 替换字符串
                字符串.toUpperCase()将字符串转成大写；
                字符串.toLowerCase()将字符串转成小写；
                字符串.concat('字符串','字符串','字符串'...)合并字符串
                字符串.trim()去掉字符串的首尾空格；                
                字符串.trimLeft()去掉字符串左边的空格；
                字符串.trimRight()去掉字符串右边的空格；
                // 字符串.charCodeAt(0) 通过下标找字符的Unicode编码：  了解
                // String.fromCharCode(20320)通过Unicode编码找汉字     了解
                字符串.split('分隔符')将字符串分割为数组；当分隔符为a时，在有a的地方就会分隔开，并且删除这个分隔符a
                        用在数组中，会将每一项单独分割成数组；
                        var a='a=1&b=2';
                        a.split('&').forEach(item=>{
                                console.log(item.split('='))//[a,1]  [b,2]
                        })
        注：所有字符串方法都会返回新字符串。它们不会修改原始字符串，所以使用字符串的方法时要赋值在一个新的变量里；

        字符传的运算规则：
                        +  数字会转成字符串
                        - * / %字符串会转化为数字 
        引号嵌套规则：
                单引号不能套单引号，双引号不能套双引号；单引号可以套双引号；
                拼接：
                        box.innerHTML='<div>'+123+'</div>\
                                        <div>'+456+'</div>\
                                        <div>'+789+'</div>'
                                        换行时，需要通过转义字符'\'进行转换或用'+'拼接，如果填写一些变量或数值，还要进行字符串拼接
                                        拼接变量时，需要用'+'拼接
                        以上写法太麻烦
        
es6字符串拓展：       
        模板字符串：       
                书写：
                        模板字符串``反引号
                        模板字符串输出${}
                模板字符串与之前字符串的区别：
                        1.模板字符串可以换行书写；
                                        var str=`<div>
                                                </div>`
                        2.模板字符串可以直接在字符串里面拼接变量；
                                        var num=100;
                                        var str=`<div>${num}</div>`
                案例：
                        html布局：<table><thead><tr><th>姓名</th><th>年龄</th><th>性别</th></tr><tbody></tbody></thead></table>
                        script: 
                                const arr = [{name: '小明', age: 10,sex: '男'},{name: '小红',age: 20,sex: '女'},{name: '小兰',age: 30,sex: '女'}]
                                var tbody = document.querySelector('tbody')
                                arr.forEach(item => {
                                        var str = `<tr>
                                                        <td>${item.name}</td>
                                                        <td>${item.age}</td>
                                                        <td>${item.sex}</td>
                                                </tr>`
                                        tbody.innerHTML += str
                                })	



                includes  查看当前字符串是否包含这个字符 返回布尔值
                                var str = 'hhaha';
                                str.includes('ha') //true
                startsWith 头部是否包含这个字符  返回布尔值
                                str.startsWith('h')  //true
                endsWith  尾部是否包含这个字符，返回布尔值；

                字符串.repeat(次数) 字符串重复    返回新的字符串；
                补全：返回新的字符串 (长度,补充的内容)   少补多退原则   不改变原字符串；
                        如果长度小于原字符串的长度，直接输出原字符串；
                        数长度时，先数原字符串的长度，然后再数新添加的；
                        padStart(长度,补充的内容)  头部补充
                                var str='abc';
                                var str1=str.padStart(10,'dc')//少则补

                        padEnd(长度,补充的内容)   尾部补充
                                var str2=str.padEnd(10,'dcdcdcdcdcdcdcdcdc')//多则退
                        日期补全：
                                let s1 = '3.23';
                                let s2 = '10.01';
                                console.log(s1.padStart(10,'2020.0'))//2020.03.23
                                console.log(s2.padStart(10,'2020.0'))//2020.10.01  多则退
                        定时器：
                                var num = 0
                                setInterval(function(){
                                        num++
                                        let str = num.toString()
                                        console.log(str)
                                        box.innerHTML = str.padStart(10,0)
                                        //相当于原字符串一直改变；
                                },500)
                for...of 遍历有长度的类数组、数组；
                                var arr=['a','b','c'];
                                for(var x of arr){
                                        console.log(x)//每一项
                                }                
数组：Array
                创建数组：
                        (1) var arr=new Array(1,2,3,4,5)
                        (2) var arr=[1,2,3,4,5]  常用方法
                数组.length：返回数组的长度
                        数组[0]允许通过下标访问字符：
                        访问数组中最后一位元素，数组.length-1;
                可以用for循环遍历数组；
                        for(var i=0;i<arr.length;i++){}
                forEach():也可以用遍历数组；
                        数组.forEach(function(item,index,arr){
                                console.log(item)数组中的每一项；
                                console.log(index)数组中每一项的下标；
                                console.log(arr)返回整个数组
                        })
                typeof判断类型的：
                        var str='123'
                        console.log(typeof str)//string
                字符串.join('分隔符') 通过分隔符拼接成字符串  注：不会删除分隔符；
                数组.push('5')原数组尾项添加；返回新数组的长度；
                数组.pop()原数组尾项删除；返回删除的元素
                数组.unshift('5')原数组首项添加；返回新数组的长度；
                数组.shift()原数组首项删除；返回删除的元素
                数组.splice(1,4,'a')插入、删除、替换元素
                                第一个参数：起始下标；
                                第二个参数：删除的长度；
                                第三个参数：添加的值；
                数组.concat(数组,数组...)合并数组，不会改变原来的数组，会返回一个新数组
                数组.slice(起始下标,结束下标)截取数组，注：但不包含结束下标；如果只有一个参数，就从起始下标截取到最后；
                数组.indexOf(元素,开始下标)通过数组中的元素查找下标；
                        元素：要查找的元素
                        开始下标，从给定的下标位置开始查起，如果省略，则从0查起.
                                ['a', 'b', 'c'].indexOf('a'); // =>0
                                ['a', 'b', 'c'].indexOf('a', 1); // =>-1
                数组.reverse()数组的反转；
                toString() ：转换成字符串：将数组中所有元素通过一个英文逗号','拼接为一个字符串,强行转化循环
                Array.isArray(arr) 判断是不是 数组  返回布尔值  
                                console.log(Array.isArray([]))//true
                every(每一项,下标,整个数组) ：依次遍历元素,判断每个元素是否都为true,返回布尔值
                        如果都满足条件的话为true，只要有其中一项不满足，那么就为false立即结束遍历（必须要有返回值return）
                        var arr=[0,2,0,3,4,5]
                        var arr1=arr.every(function(a,b,c){
                                a为每一项
                                b为每一项的下标
                                c返回整个数组
                                return a>0
                        })
                        console.log(arr1)
                filter(每一项,下标,整个数组)过滤，依次遍历元素，返回包含符合条件元素的新的数组(必须要有返回值)
                        var arr=[1,2,3,4,5,6,7,8];
                        var arr1=arr.filter(function(a,b,c){
                                a为每一项
                                b为每一项的下标
                                c返回整个数组
                                return a%2==0
                        })
                        console.log(arr1)
                map(每一项,下标,整个数组)   依次遍历并计算每个元素，返回计算好的元素的新数组(必须要有返回值)
                filter是满足条件的留下，是对原数组的过滤；map则是对原数组的加工，映射成一对一映射的新数组
                        var arr = [1,2,3,4,5,6,7,8,9,10]
                        var newarr = arr.map(function(a,b,c){
                                a为每一项
                                b为每一项的下标
                                c返回整个数组
                                return a*2
                        })
                        console.log(newarr)
                sort()数组的排序；返回值：无(在原先数组里进行排序操作)
                   升序
                        var arr=[1,2,3,4,5,6];
                        var arr1=arr.sort(function(a,b){
                                return a-b
                        })
                        console.log(arr1)
                         console.log(arr)
                   降序
                        var arr=[1,2,3,4,5,6];
                        var arr1=arr.sort(function(a,b){
                                return b-a
                        })
                        console.log(arr1)
                  给数组随机排序
                        var arr=[1,2,3,4,5,6];
                        var arr1=arr.sort(function(a,b){
                                return Math.random()-Math.random()
                        })
                        console.log(arr1)
                将一组商品数据通过销量进行排名；
                        var arr=[
                                {'name':'香蕉1',x:100},
                                {'name':'香蕉2',x:400},
                                {'name':'香蕉3',x:500},
                                {'name':'香蕉4',x:200},
                                {'name':'香蕉5',x:450}
                        ]
                        var arr2=arr.sort(function(a,b){
                                console.log(a,b)//a,b为对比的每一项
                                return b.x-a.x
                        })
                        console.log(arr2)
                   找数组中的最大值
                        Math.max(1,2,3,4)  注：括号中只能填序列，不能写数组；
                        Math.max.apply(null,[1,2,3,4]) 
                   找数组中的最小值
                        Math.min(1,2,3,4)  注：括号中只能填序列，不能写数组；
                        Math.min.apply(null,[1,2,3,4]) 
                  in：用来做判断的；返回布尔值
                        数组：判断数组中有没有这个下标；
                                var arr=[1,2,3];
                                console.log(2 in arr)
                        对象：判断对象中是否有这个属性；
                                var json={
                                        'name':"小明"
                                }
                                console.log('name' in json)
        拷贝问题
           浅拷贝：相当于复制内存地址；会相互影响
                Array类型是一种引用类型；当数组a复制给数组b时，对数组b进行元素修改，数组a也会发生修改。
                例：
                        var arrA=[1,2,3,4,5];
                        var arrB=arrA 把数组A 赋值给数组B
                        arrB[0]=4 对数组B 的元素进行修改
                        console.log(arrA)[4,1,2,3,4,5]数组A 的元素也发生了变更
           深拷贝：相当于复制内容  不会相互影响;
                1.push  var arrA=[1,2,3];
                        var arrB=[];
                        for(var i=0;i<arrA.length;i++){
                        arrB.push(arr[i])
                        }
                        arrB.push(5)
                        用push方法进行赋值，对数组b进行元素修改操作，数组a不发生变更。
                        console.log(arrB)
                        console.log(arrA)
                2.concat  var arrA=[1,3,4,5]
                          var arrB=arrA.concat([])
                                arrB.push(4)
                                console.log(arrA)
                                console.log(arrB)
                3.JSON.stringify        var arrA=[1,2,3,4,5];
                                        var str=JSON.stringify(arrA)
                                        var arrB=JSON.parse(str)
                                        arrB[0]=10
                                        console.log(arrA)
                                        console.log(arrB)
                4. for...in
                        var arr1=[1,2,3];
                        var arr2=[];
                        extend(arr1,arr2);
                        function extend(arr1,arr2){
                                for(var x in arr1){
                                     arr2[x]=arr1[x]
                                }
                        }

es6数组的拓展：
                includes  查找是否包含某一项 返回布尔值；
                                var arr = [1,2,3,4]
                                 arr.includes(9)  //false   数组中的元素
                Array.from() 将类数组转换为新的数组；有长度的都可以
                             1.基础用法：
                                var str='abcd';
                                var box=document.querySelectorAll('.box')
                                var str1=Array.from(str)//字符串
                                var str2=Array.from(box)//类数组；
                                console.log(str1)
                            2.进阶用法:
				var str = '324324'
				var newarr = Array.from(str,(a,b)=>{//a每一项，b下标
					return {name:a,index:b}
				})
                                console.log(newarr)//[{name: "3", index: 0},{name: "2", index: 1},{name: "4", index: 2},{name: "3", index: 3},{name: "2", index: 4},{name: "4", index: 5}]      
                        
                Array.of() 将一组数值转换为新的数组；
                                console.log(Array.of(1,2,3,4,5))//[1,2,3,4,5]
                copyWithin(开始替换的下标，开始读取的下标，停止读取的下标(不包括))  拷贝数组的一部分用来替换数组的一部分
                                var arr=['a','b','c','d'];
                                var arr1=arr.copyWithin(2,0,2)
                                console.log(arr1)//['a','b','a','b']替换的长度取决于拷贝的长度，如果拷贝的长度大于  开始替换的下标到数组最后一位下标  就停止；
                find(每一项,下标,数组本身)   //返回第一个符合条件的元素 如果没有返回undefined
                                var arr=[1,2,3,4];
                                var arr1=arr.find(function(a,b,c){
                                        return a>2    
                                })
                                console.log(arr1)//3
                findIndex(每一项,下标,数组本身)   //返回第一个符合条件的下标
                                var arr=[1,2,3,4];
                                var arr1=arr.findIndex(function(a,b,c){
                                        return a>2    
                                })
                                console.log(arr1)//2
                fill(填充值,填充的起始下标,填充的结束下标(不包含))使用制定的元素填充数组，其实就是用默认内容初始化数组。
                                局部重置：
                                var arr=[1,2,3,4,5];
                                        arr.fill('a',1,4)
                                console.log(arr)
                                全部重置：
                                arr.fill('a')
                entries() 遍历所有键值对；
                                var arr=['a','b','c'];
                                for(var key of arr.entries()){ //返回数组，下标+每一项元素
                                        console.log(key)//[0,'a'] [1,'b'] [2,'c']
                                }
                keys()     遍历所有键
                                for(var key of arr.keys()){
                                        console.log(key)//1,2,3
                                }
                values()  遍历所有值
                                for(var key of arr.values()){
                                        console.log(key)//a,b,c
                                }
                
                                
对象Object：    没有长度，没有下标；    
                一组属性的无序集合;
                创建：两种  标准的json对象，必须是双引号
                        1.  内置构造函数创建
                             var json=new Object()
                             根据传入的参数决定对象类型；
                             json.name='王小明'
                                json.show=function(){
                                        console.log(1)
                                }
                        2.  字面量创建
                                var json={
                                name:'小红',
                                sex:'女'
                        }
                        
                访问对象中的属性:
                                json.name   或   json['name']      获取某个属性值
                访问对象中的方法：
                                var person={
                                        name:'小明',
                                        age:10,
                                        showName:function(){
                                                return json.name
                                        },
                                        json:['music','skiiing']
                                }
                                person.showName()    对象的方法调用
                                person.json[0]       数组属性的一个子元素
                新增、修改、删除
                                删除属性
                                        delete json.name  
                                添加一个死的key值
                                        json.name='小明'  如果json对象中有这个属性：修改；
                                        json.name='小明'  如果json对象中没有这个属性：添加；
                                添加动态值：
                                       1. var a='c';
                                        json[a]='ccc'//这儿用的a是变量，所以要用[];
                                        json[a]获取到变量a的值，c='ccc'
                                       2. var json={};
                                        json['a']=c;
                                        console.log(json)//{'a':'c'} 
                for...in 一般循环没有长度的类数组或对象；
                        for(var x in json){
                                console.log(x) 返回属性
                                console.log(json[x])   返回属性值  注：x是变量，要用[]
                        }
                JSON.parse: 将json类型的字符串转json对象，只能解析标准类型的json字符串(双引号)；
                        var str='{"name":"小明","age":10}'
                        var json=JSON.parse(str)
                JSON.stringify: json对象转json类型的字符串,返回新的对象
                        var json={name:'小明'}
                        var str=JSON.stringify(json)
                eval:让字符串可以变成被执行的代码指令；
                        1. var a='var b=10';
                                eval(a)
                                console.log(b)
                        2. 可以将不标准的json类型的字符串转换成json对象；
                        var str='{'name':'小明','age':10}';
                        var arr=eval(`(${str})`);       或 var arr=eval('('+str+')')
                        console.log(arr)
                注：slice()、indexOf()、lastIndexOf()、concat()工具方法通用

es6对象的拓展：
                对象中的属性与方法的简写：
                        属性的简写：如果对象的属性取值是某个变量 , 可以使用设置的变量并且可以简化；
                                   对象的属性名与变量名一致时，可以简化；
                                var a=12;
                                var json={
                                        a:a
                                }=>    var json={
                                       a
                                       }
                                
                        方法的简写：
                                  var json={
                                          b:function(){
                                                console.log(1)
                                          }
                                }=>     var json={
                                                b(){
                                                console.log(1)
                                                }
                                        }
                                        json.b()调用对象中的方法
                Object.is():  用来比较两个值是否严格相等 与严格比较运算符(===)的行为基本一致(值与类型都相等)；
                        例：
                           console.log(Object.is(null,undefined))//false;
                Object.assign()  对象的合并
                        语法：
                                Object.assign(对象，对象，对象)            
                        会将合并好的对象放在第一个对象中；
	                Object.assign(target, source1, source2...) 将source1, source2...中的属性和方法都合并到target
                        例：
                                var o1={
                                        name:'小明'
                                }
                                var o2={
                                        age:12,
                                }
                                Object.assign(o1,o2)
                                console.log(o1)
                                // 返回：
                                //         o1={
                                //            name:'小明',
                                //            age:12
                                //         }
                Object.keys(对象)  返回新的数组：所有键
                        例：
                        var o={
                                name:'小明',
                                age:12,
                                sex:'男'
                        }
                        var o1=Object.keys(o)
                        console.log(o1)//['name','age','sex'];
                Object.values(对象)  返回新的数组：所有值；
                        例：
                                var o1=Object.values(o)
                                console.log(o1)//['小明',12,'男']
                Object.entries(对象)  返回新的数组：每一对键值对为一组
                        例：
                                var o1=Object.entries(o)
                                console.log(o1)//[['name','小明'],['age',12],['sex','男']]

定时器：setInterval()/setTimeout()
                setInterval：
                        setInterval(回调函数,毫秒数) 第三个参数是给回调函数传参的(实参)，可以一次传多个
                                每隔多久执行一次；会不停地调用函数，直到 clearInterval() 被调用或窗口被关闭。
                        创建定时器      
                                        var tid=setInterval(fn,1000)
                        再次调用定时器 
                                        tid=setInterval(fn,1000)
                        清空定时器
                                        clearInterval(tid)
                setTimeout: 

                        setTimeout(回调函数,毫秒数) 
                                隔多久执行一次，注：只执行一次
                清空定时器：
                                clearInterval()
                                clearTimeout()
                带不带括号问题：
                                        
                        setInterval(fn,200)调用函数这个动作交给定时器完成的，所以不需写括号；
                        box.onclick=fn;调用函数这个动作交给box的点击事件完成；事件接收的不是函数，而是函数的返回值
                设定时间有默认值：
                                两个定时器各有各的默认值，当设定的时间小于默认值，浏览器会执行默认值
                多线程：
                        相当于异步请求数据：延迟定时器会有个等待的时间，等待的过程中并不会影响后续代码的执行；
                        console.log(1)
                        setTimeout(function(){
                                console.log(2)
                        },100)
                        console.log(3)
                        setTimeout(function(){
                                console.log(4)
                        },50)
                        输出结果：1342
                案例：
                        有时会用延迟定时器来渲染动画效果：给动画效果一个过渡时间
                        box.style.left = '-100px'
                        setTimeout(function(){
                           box.style.left = '100px'
                        },200)
随机数：
                Math.random()     返回 0（包括） 至 1（不包括） 之间的随机数：
                返回两数之间的随机数(包括最大值和最小值)
                        function fn(max,min){
                                return Math.round(Math.random()*(max-min))+min
                        }
                        fn(10,20)
                生成随机颜色的函数
		function mathColor(){
			return `rgb(${Math.round(Math.random()*233)},${Math.round(Math.random()*233)},${Math.round(Math.random()*233)})`
		}
                Math.round() 四舍五入
                Math.max() 最大值
                Math.min() 最小值
                Math.abs() 绝对值
                Math.ceil()向上取整；只要有余数就+1并且舍去小数部分；
事件：
        什么是？
        是指用户在某个元素中通过某种行为所执行的一些事情；
        事件的三要素：
                事件源：是指在哪个元素引发的事件；
                事件：执行的动作；如：单击、双击
                事件驱动程序:即执行的结果；即所执行的函数
事件分类：  
        事件绑定：dom.on+事件类型   
        事件类型：
           鼠标事件：click(单击) dblclick(双击) contextmenu(右键) wheel(滚轮) mousemove(鼠标移动) 
                    mouseover(鼠标移入) mouseout(鼠标移出) mouseenter(鼠标移入) mouseleave(鼠标移出)
                    mousedown(鼠标按下)mouseup(鼠标抬起)；
           键盘事件：keydown(键盘按下) keypress(键盘按压) keyup(键盘抬起)  只能绑定给body、html、document、window
           表单事件：focus(获取焦点) blur(失去焦点) input(只要用户有输入就触发) 
                    change(失去焦点并且内容发生变化,只能用于表单事件)   onsubmit(提交按钮时)    onreset(重置时)
           浏览器事件：load(页面加载完成时) resize(浏览器窗口大小发生变化时) scroll(页面滚动时) online(上线时) offline(下线时)
        scroll事件
                scrollTop   滚动条距离顶部的偏移:
                        可以设置给整个页面：
                                有兼容问题：      document.documentElement.scrollTop||document.body.scrollTop定义在滚动事件中； 兼容ie的
                        也可以设置给某个元素：
                                box.scrollTop   box元素中的滚动条距离box顶部的距离
                        案例问题：
                                在滚动事件外面获取滚动值时，只会获取一次固定的值；
                                在滚动事件内获取滚动值时，每滚动1像素就会获取一次滚动值；
                案例：
                        留言本：
                        text_box.scrollTop = text_box.scrollHeight(案例在王超刚的留言本)总是让最新添加的留言最先显示
                        原理：滚动距离总是小于文档的高度
                                每次都让最新添加的这条留言都显示出来，就设定这个页面scrollTop的值为最大值
                                如果给这个元素的scrollTop设定的值超过了scrollTop的最大值，滚动条依然在最大值处；然而元素的scrollHeight值永远都大于scrollTop值；
                                所以这个原理成立；
                案例：
                    懒加载=>延迟加载：
                                原理：先只加载页面上所看到的图片，等滚动到可视区最下面时，再加载所需的图片
                                实现方式：
                                        1.先只加载页面上所看到的图片，等滚动到页面下面时，再加载所需的图片。 王超刚懒加载
                                                页面中的公式：页面：元素.offsetTop<=页面的scrollTop+页面的clientHeight  
                                                元素中的公式：子元素.offsetTop-父元素.offsetTop<=元素.scrollTop+元素.offsetHeight
                                                注元素.offsetTop距离有定位的父元素的距离是不变的；当滚动的距离大于等于元素的距頂距离时，元素显示在页面最上方
                                        2.图片：可以将图片的地址设置到一个自定义的属性中，当页面滚动满足条件时，
                                                再将图片的地址设置到src属性中； 图片延迟加载
                                区别：一般用于图片，DOM元素是一直存在的，但是没有加载，用哪一个部分加载哪一部分；
                    加载可视区域的图片：
                                原理：
                                        图片盒子的距离顶部的距离<滚动的距离+可视区高度&&图片盒子距离顶部的距离+图片盒子的高度>滚动的距离 
                                        只要是在可视区域内的图片都会加载；
                                        注：需要给每个图片设置个盒子为了获取到每个图片距离顶部的距离；

                   瀑布流：    
                           特点：宽度一致，高度不一致的布局
                           原理：当页面滚动到底部时，再加载所需的dom元素；
                           实现方式：先通过计算一排里面可以容纳多少列元素；后再判断哪一列元素的高度最短，就将下一个元素放到该列；
                                  之后再判断放入该元素之后所形成的新的整排元素内，哪一列元素最短，再把下一个元素放置该列，以此类推
                           方法：
                               1.王超刚瀑布流：用for循环进行对数据循环，通过数组的sort方法给三列高度进行升序排序；所以每次循环都是数组中第0列的高度最小；
                                            然后给第0列进行追加数据，将这些封装在函数中，添加滚动事件，每次滚动满足,公式：
                                            页面.scrollTop+clientHeight>=页面.scrollHeight 时，调用此函数；
                           区别：
                                dom是不存在的，当页面滚动到底部时，再重新生成dom；如果生成的dom过多会造成页面卡顿；
                   吸顶导航：
                                原理:滚动距离大于等于元素距离页面顶部的距离；
                                公式：页面.scrollTop>=元素.距頂距离；
                                有bug：当导航设置了固定定位就不占位了，原来占的位置会空缺出来让下一个元素站位；
					解决方法：1.添加一个与导航同宽同高的空元素设置成不显示，当导航设置了固定定位时再显示；
						2.给导航的外部包装一个元素，只设置导航元素的固定定位；导航的父级会替他站位；

                scrollHeight  文档的高度； 可以设置给整个页面、某个元素，
                        document.documentElement.scrollHeight;网页内容的实际高度
                        box.scrollHeight  box元素内容的实际高度；
                scrollWidth  文档的宽度

        onload事件：加载
                通常与window绑定
                语法：window.onload=function(){};
                load与ready的区别：
                                window.onload：
                                        执行时机：在结构和样式、外部 js 以及图片加 载完才执行onload中的js代码； 
                                        执行次数：在一个页面中只能写一次，写多次前面的会被覆盖，只执行最后一次；

                                $(document).ready()：
                                        执行时机：当页面中的dom结构加载完成时，再执行jq代码；
                                        执行次数：在一个页面中可以写多次，不会出现覆盖情况；
                                        简写：
                                                $().ready()
                                                $(function({}))
        resize：浏览器窗口大小发生变化时
        online上线时
        offline下线时

        click：鼠标单击事件：鼠标完整的左键按下+抬起)dblclick:鼠标双击事件：鼠标完整两次单击
        contextmenu:鼠标右键事件：鼠标完整的按下+抬起
        mousemove鼠标移动事件
                一般绑将事件绑定给document，如果给具体某个元素绑定事件拖拽速度过快时会脱离元素造成bug；
                jq中用page.X/Y、$(document).width()/Height()、off()等方法来做拖拽效果；
        mouseover：鼠标移入事件)mouseout：鼠标移出
        mouseenter：鼠标移入)mouseleave：鼠标移出
        mousedown：鼠标按下) mouseup：鼠标抬起)
        wheel:鼠标滚轮事件
                兼容火狐：DOMMouseScroll
                event.wheelDelta
                //向下滚动为正值
                //向上滚动为负值

        keydown：键盘按下)  keypress：键盘按压)    keyup(键盘抬起)
                event.key    代表的是按的哪个键
                event.keyCode  代表的是按的哪个键码
                        常用键值码：
                                回车Enter=13;
                                空格=32；
                                左上右下37-40；
                                0-9：48-57；
                                a-z:65-90;
                document.onkeydown=function(event){
                        var event=event||ev;
                        if(event.key=='d'){}
                        if(event.keyCode==32){}
                }
                键盘事件只能绑定给body、html、document、window
        input： 只要有输入就会触发事件；
        change：当内容有所改变并且失去焦点时触发事件
        focus：获得焦点) 	blur：失去焦点)
        submit：提交按钮时)    reset：重置时)
        Js中取消事件：null
                document.mousemove=null;
                元素.事件=null;

事件对象：event
        事件产生时，浏览器会将事件的相关信息封装成一个对象，该对象就是事件对象；
        event.clientX/Y:鼠标事件产生时，鼠标距离浏览器左上角的坐标；
        event.offsetX/Y:鼠标事件产生时，鼠标距离产生事件的元素的左上角的坐标；
        event.pageX/Y:鼠标事件产生时，鼠标距离显示页面内容的左上角的坐标;
        event.screenX/Y:鼠标事件产生时，鼠标距离电脑屏幕的左上角的坐标；
        兼容：
                在ie中获取event对象用window.event;
                在非ie中获取event对象，用传参的方式
                        xxx.onclick=function(e){
                                console.log(e)
                                兼容问题：var e=e||window.event;
                        }
        event.key    代表的是按的哪个键
        event.keyCode  代表的是按的哪个键码
        event.wheelDelta
                //向下滚动为正值
                //向上滚动为负值
事件绑定：
        DOM 0级 事件：div.onclick=function(){}
                只能绑定一个事件处理函数；
                //用法：
                        div.onclick=function(){
                                console.log(1)
                        }
                        div.onclick=function(){
                                console.log(2)
                        }
                        //绑定多个，前面绑定的会被覆盖掉；
        DOM 2级 事件：
                addEventListener 标准浏览器
                attachEvent() IE低版本浏览器
                

                1语法：元素.addEventListener('click',function(){},true/false);
                注：   可以给元素绑定多个同类型事件,顺序绑定顺序执行； 
                参数:   1 事件类型（不需要on）
                        2 执行的函数；
                        3 布尔值；true：执行事件捕获/false：执行事件冒泡;不写默认为事件冒泡
                //用法：
                        div.addEventListener('click',function(ev){
                                //事件对象的方式和之前一样；
                                var e=ev||window.event;
                                console.log(e)
                        })
                        div.addEventListener('click',function(ev){
                                console.log(1)
                        })
                        //可以绑定多个不会覆盖

                2语法：元素.attachEvent();
                注：   可以给元素绑定多个同类型事件,按照绑定的顺序倒序执行； 
                参数：
                        1 事件类型（on+事件类型）
                        2 执行的函数；
                div.attachEvent('onclick',function(){
                        console.log(window.event)//获取事件对象
                        console.log('click')
                })
取消事件绑定：
                在标准浏览器中：元素.removeEventListener('事件类型',执行的函数)
                注：绑定时必须将函数写到外面，因为取消事件绑定时需要知道函数的地址；
                用法：
                        div.addEventListener('click',fn)
                        function fn(){
                          console.log('click')
                        }
                        div.removeEventListener('click',fn)
                
                IE低版本浏览器：元素.detachEvent('事件类型',执行的函数)
                用法：
                        div.atachEvent('onclick',fn)
                        function fn(){
                          console.log('click')
                        }
                        div.detachEvent('onclick',fn)

事件流：
        当要触发一个元素的某个事件时，如果这个元素的父级元素有同样的事件类型，那么就会触发事件冒泡或事件捕获；
        事件目标：
                准确触发行为的元素；
        事件冒泡：一般所有浏览器都按事件冒泡执行；
                触发事件时，从目标元素向父元素依次触发，直到window
                box->body->html->document->window
        事件捕获：ie按事件捕获执行
                触发事件时，从父元素window向目标元素依次触发；
                window->document->html->body->box
                addEventListener(事件类型,执行的函数,true/false);
                绑定事件的第三个参数：true：设置执行事件捕获，false设置执行事件冒泡，不写默认为事件冒泡
        阻止事件冒泡: 指这个元素不向上传播；
                        1.事件对象方式：event.cancelBubble=true；是属性
                        2.事件对象方式：event.stopPropagation()  方法
                案例：
                        div.onclick=function(){
                                list.style.display='block'
                        }
                        document.onclick=function(){
                                list.style.display='none'
                        }
                        //document属于div的一个父级，并且document有了与div元素同类型的事件；会形成事件流；
                        //当触发document事件时不会形成事件流，因为document的父级元素没有与它同类型的事件；所以不会造成影响
                        //当触发div事件时形成事件流div->document;document是最后执行的，所以造成了覆盖div的事件，
                        //那么阻止事件冒泡，应该阻止div身上的事件冒泡；
                        注：当div的子元素，也有了与div的同样类型的事件类型时，div的子元素也会形成事件流，因为只在div元素上设置了阻止事件流
                        ，所以传播到div身上时，就会停止传播；子元素->div;阻止这个元素不想上传播，而不是阻止子元素向上传播；

阻止默认事件：
        浏览器的默认行为：
                        a标签的跳转；
                        在网页上点右键鼠标出现菜单；
                        点击form表单中的提交按钮会产生条行为，并刷新页面；
                        在页面上滚动鼠标滚轮，网页的滚动条会动；
        阻止默认事件：
                1.return false;
                        主要用于普通事件：onclick
                2.事件对象的方法：event.preventDefault()
                        主要用于事件监听用的addEventListner
                //取消a标签的默认行为；(需要先判断默认行为是从什么事件类型中产生出来的，然后在事件触发时阻止默认事件)
                        a.onclick=function(ev){
                                var e=ev||window.event;//可以省略window，调用window的方法或属性可以省略window；
                                e.preventDefault();
                                或
                                return false
                        }
                //取消右键的默认行为：
                        document.oncontextmenu=function(ev){
                                var e=ev||window.event;
                                e.preventDefault();
                                或
                                return false
                        }



DOM操作
        设置css样式：
                使用style和style.cssText：
		style:给元素设置css样式；一次只能设置一个；赋什么值，就返回什么值
		style.cssText:给元素设置css样式，一次可以设置多个；style.cssText='width:500px;height:500px;'赋什么值就返回什么值
                注：在js、jq中，要将带连字符类的css属性值(font-size)，写成驼峰写法在使用(fontSize)；
        改变html中的内容innerHTML和innerText
		innerHTML：
		获取元素的内容：元素.innerHTML 不会解析标签
		设置元素的内容：元素.innerHTML='你是谁'(标签会被当做内容替换为设置的内容)
                可以新建标签
                        box.innerHTML+=`<div>${div}</div>`  添加多个使用+=
                        box.innerHTML=`<div>${div}</div>`  添加一个使用=
		innerText: 
		获取元素的内容：元素.innerText 会解析标签
		设置元素的内容：元素.innerText='你是谁'(标签会被当做内容替换为设置的内容)
        DOM元素
                创建元素createElement
                   var div=document.createElement('div')
                   创建图片：
                        var img=new Image()
                        img.src=''
                        img.appendChild(box)
                   用innerHTML创建元素
                        box.innerHTML+=`<div>box</div>`
                追加元素appendChild()：向父元素中最后一个节点插入
                        box.appendChild(div)
                        父元素.appendChild(插入的元素)
                插入元素insertBefore
                        box.insetBefore(div,li)
                        父元素.insetBefore(新建元素,插入哪个元素的前面)
                移除元素removeChild
                        ul.removeChild(li[0])
                        父元素.removeChild(要移除的元素)
                替换replaceChild
                        父元素.replaceChild(新建元素,被替换的)
                克隆cloneNode(true)
                        var cloneDiv=box.cloneNode(true)
                                克隆生成的节点=被克隆节点.cloneNode()
                        写参数true会克隆元素中的内容或文本；
                        不写参数true不会克隆元素中的内容或文本
        添加类名
                className替换/覆盖类名，会覆盖掉之前的类名
                classList.add在元素中添加一个或多个类名；不会覆盖掉之前类名-->addClass()
                        元素.classList.add('类名')
                        注:一次只能添加一个类名，添加多个需要多次使用classList.add
                                div.classList.add('box')
                                div.classList.add('box1')
                classList.toggle('cc')如果有这个类名(如果没有)，就删除(就添加)-->toggleClass()
                        元素.classList.toggle('类名')
                                div.classList.toggle('box')
                classList.contains()查找你当前的元素里面有没有这个class类名；返回布尔类型;-->hasClass()
                        元素.classList.contains('类名')
                                console.log(div.classList.contains('box'))
                        一般用于if判断
                classList.remove()移出类名；-->removeClass()
                        元素.classList.remove('类名')
                                div.classList.remove('box')
                        不写参数不起作用；
        设置属性
                注：是标签属性(class、id、title)，不是css属性(width、height、background)
                getAttribute()获取属性；
                        console.log(元素.getAttribute('class'))
                setAttribute(属性,属性值)设置属性，可以修改、添加属性；
                        元素.setAttribute('class','box1')  如果已有此属性，修改
                        元素.setAttribute('id','box2')     如果没有此属性，添加
                removeAttribute(属性)删除属性
                        元素.removeAttribute('id')
        元素与节点：
                childNodes获取所有子节点：元素节点+文本节点(浏览器会把元素与元素之间的回车或空格看成文本节点)
                        父元素.childNodes  获取某个元素中的所有子节点；返回类数组
                        父元素.childNodes[0] 获取某个元素中的第几个节点；
                nodeValue获取文本节点值；
                        父元素.childNodes[0].nodeValue
                nodeType获取节点类型；
                        元素返回1，文本返回3，属性2，注释8，文档9
                        父元素.childNodes[0].nodeType
                nodeName节点名称
                        父元素.childNodes[0].nodeName  文本节点名称 返回 #text
                        父元素.childNodes[1].nodeName  元素节点 返回 LI元素节点；
                parentNode获取父节点:获取直接父元素；只能获取一个直接父元素
                        元素.parentNode
                firstChild获取第一个子节点；文本节点与元素节点都找
                        父元素.firstChild
                firstElementChild获取第一个子元素节点 只找元素节点
                        父元素.firstElementChild
                lastChild获取最后一个子节点； 文本节点与元素节点都找
                        父元素.lastChild
                lastElementChild获取最后一个子元素节点；只找元素节点
                        父元素.lastElementChild
                nextSibling获取下一个兄弟节点；文本节点与元素节点都找
                        父元素.childNodes[1].nextSibling
                nextElementSibling获取下一个兄弟元素节点；只找元素节点
                        父元素.childNodes[1].nextElementSibling
                previousSibling获取上一个兄弟节点；文本节点与元素节点都找
                        父元素.childNodes[1].previousSibling
                previousElementSibling获取上一个兄弟元素节点，只找元素节点

                parentElement 找元素的父级
        //删除无用的空白节点
                function fn(node){//传入父节点
                        for(var i=0;i<node.childNodes.length;i++){
                                                                //^开头 \s空白字符  $结尾
                        if(node.childNodes[i].nodeType==3 && /^\s+$/.test(node.childNodes[i].nodeValue)){//检测这个节点值的开头到结尾是否为空白
                                node.childNodes[i].parentNode.removeChild(node.childNodes[i])
                        }
                        }
                }
                fn(ul)
                console.log(ul.childNodes)

        DOM尺寸
                offset:
                offsetWidth获取盒子的宽度(width+border+padding)
                        元素.offsetWidth 
                offsetHeight获取盒子的高度(Height+border+padding)
                offsetLeft获取元素距离父级(有定位的)的左边距离
                        元素.offsetLeft 
                offsetTop获取元素距离父级(有定位的)的上边距离；
                        常用：
                                获取元素的距頂距离：元素.offsetTop;
                                吸顶条：
                                        当在滚动事件中的距頂距离改变了，就不能在滚动事件中获取这个元素的距頂距离；比如吸顶条等；
                                                特别注意：获取元素的距頂距离不能在滚动事件中获取：因为向上滑动时，如果满足了条件，
                                                会将元素设置成固定定位top:0，此时的距頂距离就变成了0；
                                                在滚动事件外获取：只会获取一次，是固定的值；
                                        如果在滚动事件中的距頂距离没有改变，可以在滚动事件中获取这个元素的距頂距离；比如延迟加载、瀑布流等
                                
                        计算符号:
                                >= : 包括等于时、大于时； 5>=5可以   100>5可以
                                > : 必须大于时才符合条件；100>5可以 5>5不可以
                getBoundingClientRect().width/Height获取元素的宽/高
                getBoundingClientRect().left/top获取元素距离当前视口的左上角的距离；

                client:
                clientWidth:可视区域的宽度(content+padding)
                                获取浏览器可视区域的宽度：
                                var ksw=document.documentElement.clientWidth||document.body.clientWidth;
                clientHeight:可视区域的高度(content+padding)
                                获取浏览器可视区域的高度：
                                var ksw=document.documentElement.clientHeight||document.body.clientHeight;
                clientLeft:左边框线的宽度
		        console.log(oBox1.clientLeft)
                clientTop：上边框线的宽度

                scroll:
                scrollWidth:文档的宽度(一般用不到)
		        console.log(oBox1.scrollWidth)
                scrollHeight文档的高度
                scrollTop 纵向滚动条距离页面顶部的距离；
                scrollLeft 横向滚动条距离页面最左边的距离；

                window.screen.height屏幕的高度
                window.screen.width屏幕的高度
        注：所有的window的属性、方法使用时可以省略window；
                
非行间样式：
                获取行间样式：
                        元素.style.width只能获取行内样式；注：行间样式：在标签内写的样式--》内嵌样式
                获取非行间样式：既可以获取行间样式，又可以获取非行间样式；
                        function getStyle(obj,name){
                                if(obj.currentStye){
                                        //兼容IE
                                        return obj.currentStyle[name]
                                }else{
                                        //IE之外的浏览器
                                        return getComputedStyle(obj,false)[name]
                                }
                        }
                        console.log(getStyle(box,'width'))
                getStyle(元素,'属性')

                
                

数值：
                toFixed(2)四舍五入,括号内规定保留几位小数
                        2.345.toFixed(2)保留两位小数
                        当遇到字符串-0就可以将字符串转换成数值；
                isNaN()判断是不是NaN,返回布尔类型；如果是返回true，如果不是返回false；
                        console.log(isNaN(10))//false 
                        console.log(isNaN('nan'))//true
                parseInt()取整
                        console.log(parseInt(1.2333))
                parseFloat()取浮点数
                        console.log(parseFloat(1.333333))
正则RegExp: 
                创建： 
                1.     var patt=new RegExp('表达式模型','修饰符')   ('box','img')
                2.     var patt=/box/img
                    i:忽略大小写；
                    m:执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)
                    g:执行多行匹配；
                作用：主要用于文本搜索和文本替换；
                serach()返回正则表达式相匹配的子字符串首次出现的起始位置,如果没有找到返回-1；
                                var str='kaasassfjsaesfjae'
                                var reg=/fj/mg
                                console.log(str.search(reg))
                match()返回匹配到的所有，返回数组类型
                                console.log(str.match(reg))
                replace(reg，新)替换，将正则表达式中相匹配的子字符串替换为新的字符
                                console.log(str.replace(reg,'表情'))
                split()分割，去掉分隔符；
                                console.log(str.split(reg))
                                应用：
                                        将split与循环搭配使用：可以将数组中的每一项单独分成一个数组
                                        const obj={};
                                                cookie.split('; ').forEach(item=>{//此处传了一个形参，可以省略小括号
                                                let [k,v]=item.split('=')//['n',9] k='n' v=9
                                                obj[k]=v//把k、v当成普通的变量；相当于给对象obj添加一个动态值
                                                //obj[k]实际就是给obj对象动态添加了一个n属性，将v的值赋值给n的属性值；
                                                })
                                                return obj//{'a':10,"b":5}
                                        },
                test()方法用于检测一个字符串是否匹配某个模式
                如果字符串 string 中含有与 RegExpObject 匹配的文本，则返回 true，否则返回 false。
                                console.log(reg.test(str))
                exec()返回找到的文本；
                                console.log(reg.exec(str))
                案列：
                var str='bb1h3uh5ih6iuhiuh423hi5hi2h3iu5'
                        var reg=/[0-9]/g   匹配所有0-9的数字
                        console.log(str.match(reg).sort(function(a,b){//返回所有0-9的数字并且降序排序
                                return b-a
                        }))
                最实用的案例
                        var s3='前端知识综合演练/8.5教育产品、教学方案前端知识综合演练';
                        var r3=/前端|教育产品/igm;  匹配所有前端或教育产品关键字；
                        var rel=s3.replace(r3,function(a){
                                return '*'.repeat(a.length)
                        })
                        console.log(rel)
Date()时间
                        获取当前年份：
                                var data=new Date()
                                console.log(data.getFullYear())//2020
                        获取当前月份：
                                var data=new Date()
                                console.log(data.getMonth())//6
                                0表示1月，11月表示12月
                        获取当前日：
                                var data=new Date()
                                console.log(data.getDate())//31
                        获取当前小时：
                                var data=new Date()
                                console.log(data.getHours())//15
                        获取当前分钟：
                                var data=new Date()
                                console.log(data.getMinutes())//03
                        获取当前秒：
                                var data=new Date()
                                console.log(data.getSeconds())//03
                        获取这一周中的第几天；
                                var data=new Date()
                                console.log(data.getDay())//5 
                        获取一个时间戳：
                                var data=new Date()
                                console.log(data.getTime())//1596179476232
                        设置时间对象:
                                1.setFullYear(年份) 给时间对象设置个年份；
                                        var data=new Date()
                                        data.setFullYear(2021)
                                        console.log(data.getFullYear())
                                2.setMonth(你要设置的月份)              给一个时间对象设置年份
                                3.setDate(你要设置的日)		   给一个时间对象设置日
                                4.setHours(你要设置的小时)	   给一个时间对象设置小时
                                5.setMinutes(你要设置的分钟)	   给一个时间对象设置分钟
                                6.setSeconds(你要设置的秒钟)	   给一个时间对象设置秒钟
                                7.setTime(你要设置的时间戳)	  给一个吉时间对象设置时间戳，直接调回指定时间戳的日期
                        
                        解析数据中转换时间戳的方法：
			var d=new Date()
			var n=d.toLocaleString()   根据本地时间把Data对象(全部)转换为字符串；
			console.log(n)	//2020/4/19 下午2:10:25
			var n=d.toLocaleDateString()  根据本地时间把 Date 对象的日期部分(只转年月日)转换为字符串:
			console.log(n)	//2020/4/19           
			var n=d.toLocaleTimeString()   根据本地时间把 Date 对象的时间部分(几时几分几秒)转换为字符串：
			console.log(n)	//下午2:16:58
	一行代码解决时间戳的转换：
			console.log(new Date(时间戳*1000).toLocaleString())         
Bom操作浏览器的；
                location: 
                        用js跳转页面：
                                btn.onclick=function(){
                                        location.href='https://www.baidu.com'
                                        }
                        获取地址:当前页面地址栏的地址
                                console.log(location.href)
                                console.log(String.fromCharCode(20320))
                        网页重定向：
                                        1.location.replace('http://www.baidu.com')  特点不能退回原网页；
                                        2.location.href('http://www.baidu.com');
                                        3.location.assign('http://www.baidu.com');
                                        4.open('http://www.baidu.com');
                        reload: 强制刷新
                                location.reload()   一般放在事件中用
                open打开新的一个页面： 
                        open(url,name属性值或name名称,'设置属性，用逗号分割')  打开一个新窗口 url新窗口的地址
                           例：
                                open('https://www.baidu.com','_self/hhhh','width=200,height=400,left=100,top=300')
                close关闭页面
                                window.close()
                弹出框：
                        alert();
                        特点：会暂停页面的执行；只有一个确定按钮；
                                返回值： 输出undefined
                        confirm();
                        特点：返回的是一个布尔值：多个取消按钮；
                                返回值：
                                输出时点取消按钮会返回true；点确定按钮会返回false；
                                console.log(confirm(123))；
                        prompt();
                        特点：多个输入框，
                                返回值：
                                        输出输入框中的内容；
                                        网页重定向：
                                
kg开关
                js中的通过定义布尔值 切换布尔值状态来调整开关
                var kg=false;//kg默认值为false时，元素默认是显示的；
                oInt.onclick=function(){
                        if(kg){//第一次点击时，括号中为false，走else路线，因为这时的元素是显示状态，那么else就设置为不显示状态；
                                console.log('隐藏')
                                oDiv.style.display='block'
                                oInt.value='隐藏'
                        }else{
                                console.log('出现')
                                oDiv.style.display='none'
                                oInt.value='出现'
                        }
                        // 第一次点击走完else路线之后，要让第二次点击时走if路线将元素设置为显示状态，所以要将kg的值设置为true；
                        //让开关的值取反，就把kg的值设置为true了；
                        kg=!kg
                        console.log(kg)
                }
取消事件，在将事件加回来；
               1. //kg默认为false
                        var kg=false; 
                        //当需要执行事件时将kg改为false，当不需要执行事件时将kg改为true;
                        if(kg){
                        return
                        }
                        kg=true
                        kg=false
                2.  不需要执行事件时：box.onmousedown='';
                    需要执行事件时，box.onmousedown=fn;
条件语句：
                if语句：
                        if(){
                        当条件为 true 时执行的代码
                          }  
                          只有当指定条件为true时，使用该语句执行代码；
                    用法：
                       条件语句会隐式转换为布尔类型再进行判断：
                案例：
                        判断方法时不需要带括号，带括号就相当于调用了；
                其他类型数据转换为Boolean类型数据——Boolean()方法
		数据类型        转换为true		转换为false
		Boolean		true			false
		String		非空字符串		空字符串
		Number		非零数值		 0和NaN
		Object		任何对象		 null
		Undefined      n/a(不适用)		undefined
                          
                if...else语句
                        if(){
                                当条件为 true 时执行的代码
                        }else{
                                当条件为 false 时执行的代码
                        }
                if...else if...else语句： 来选择多个代码块之一来执行。
                        if(条件){
                                条件成立执行，后面的不在执行
                        }else if(条件){
                                条件成立执行，后面的不在执行
                        }else if(条件){
                                条件成立执行，后面的不在执行
                        }else{
                                所有没有满足的条件才执行
                        }
                try...catch(error)容错处理语句
			try{
			console.log(a)
			}catch(error){
			console.log(1)
			}
			如果try路径走不通(不会报错)，就走catch路径
			如果try路径走的通，就不走catch路径
                注：括号中的条件，可以隐式转换成布尔值；
                分号：
                        在 JavaScript 中，用分号来结束语句(可选)
循环语句：      
                while循环
                        var i=0;
                        while(i<5){
                           i++;
                           console.log(i);
                        };
                do...while循环
                        var a=0;
                        do{
                         a++;
                         console.log(a)//1
                        }while(a>20)
                        不管条件成不成立都会先执行一次do里面的内容；符合条件就继续，不符合条件就停止；
                switch语句：
                        var num=10;
                        switch(num){
                            case 1: 
                              alert(1)
                            break;
                            case 4: 
                              alert(4)
                            break;
                            case 2: 
                              alert(2)
                            break;
                            default: 
                              alert(6)
                        }
                for(var i=0;i<xxx.length;i++){};
                计算题：
                        1.
                                for(var i=0;i<10;i++){
                                        
                                }
                                console.log(i)//10 
                                当i=10不满足条件时跳出循环，输出i为10；
                        2.
                                逗号表达式：JS中一个表达式可以由多个子表达式组成
                                多个子表达式之间使用逗号隔开，最后一个子表达式的结果作为整个表达式的结果
                                
                                var m=0;
                                for(var i=20,j=10;i<25,j>2;i++,j--){
                                        m=i*j 
                                }
                                console.log(i,j) //28 2
                                                //不满足条件的时候才跳出循环，i=28,j=2的时候才不满足条件，所以i=28,j=2
                                console.log(m)	 //81
                                // i=3,j=27	最后一次循环满足条件；
                什么时候使用循环呢？
                        当需要设置多个元素时，需要for循环
                this: 
                        for循环中的this指向每一项；
                        如果是在判断语句if中的this，this指向满足条件的那几项；

                break：在循环里面可以使用一个关键字break
   			  会立即停止循环不在往下执行
                continue：在循环里面使用 continue 关键字
   			  结束循环的本次，继续下一次循环（跳过本次循环）
                
Bootstrap:css框架
                  尽量不要与框架里的类名重名，添加事件时会造成bug
TweenLite动画：
                语法：TweenLite.to(元素,帧数/时间,{
                        1.css:{					
				width:500,
				height:500,
			},
                        2.ease：缓动效果；
                        3.delay：延迟时间；
                        4.onStart:function(){在动画开始之前要执行的事}；
                        5.onUpdate:function(){在动画过程中要执行的事}；
                        6.onComplete:function(){在动画结束之后要执行的事}；
                        7.onStartScope:指定动画开始之前的时候函数中this的指向
                        8.onUpdateScope:指定动画过程中的时候函数中this的指向
                        9.onCompleteScope:指定动画结束之后的时候函数中this的指向
                        10.useFrames:确定第二个数到底是帧数还是时间
                                useFrames:true;如果值为true，设置为帧数
                                useFrames:false;如果值为false，设置为时间(默认的就是时间)
                })
                需引入封装的文件；
浏览器报错：
                浏览器在执行代码过程中，如果遇到报错，后面的代码不会执行；

                      
// 拖拽删除商品
</script>
</body>
</html> -->